﻿//---------------------------------------------------------------------
//Copyright (c) 2009, Pierre Milet
//All rights reserved.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
//OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
//TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
//---------------------------------------------------------------------

using System;
using System.Collections;
using System.Web;
using System.IO;
using System.Threading;
using System.Diagnostics;

using Microsoft.BizTalk.TransportProxy.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.Samples.BizTalk.Adapter.Common;
using Microsoft.XLANGs.BaseTypes;

namespace BizMock.Adapter.Runtime
{
	/// <summary>
	/// Utility class that implements the messaging engine contracts for dealing with
	/// the response message. It is used to wait for the response message (with timeout),
	/// retrieve the response message and notify the status of the transmission.
	/// The response message must be deleted from BizTalk message box, after it's transmitted
	/// successfully. If there is an error while processing the response message or if there is 
	/// a timeout, the response message should be suspeded.
	/// </summary>
	public sealed class BizMockResponseHandler : IBTTransmitter
	{
		private AutoResetEvent responseEvent = new AutoResetEvent(false);
		private IBaseMessage message;
		private IBTTransportProxy proxy;

		private bool timeoutExceeded = false;

		public BizMockResponseHandler(IBTTransportProxy proxy) { this.proxy = proxy; }
		public void Initialize(IBTTransportProxy proxy) { }
		public void Terminate() { }

		public bool TransmitMessage(IBaseMessage msg)
		{
			// Check if the timeout has happened, if so, reject the response.
			// Messaging engine will suspend this message
			if (timeoutExceeded)
				throw new InvalidOperationException("The response message did not arrive in time");

			this.message = msg;
			responseEvent.Set();
			return false;
		}

		public IBaseMessage WaitForResponse(int timeoutSeconds)
		{
			if (responseEvent.WaitOne(timeoutSeconds * 1000, false))
				return this.message;

			return null;
		}

		public void ResponseConsumed(Exception transmitException)
		{
			if (this.message == null)
			{
				throw new InvalidOperationException("There is no response to consume");
			}

			Batch batch = new TransmitResponseBatch(proxy, null);
			if (transmitException == null)
			{
				batch.DeleteMessage(this.message);
			}
			else
			{
				this.message.SetErrorInfo(transmitException);
				batch.MoveToSuspendQ(this.message);
			}
			batch.Done();
		}
	}
}
